package com.corpgovernment.job.service.batchimportjob;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.job.batchimport.entity.BatchImportConfig;
import com.corpgovernment.job.batchimport.BatchImportStrategy;
import com.corpgovernment.job.batchimport.entity.db.BatchImportErrorLineDo;
import com.corpgovernment.job.batchimport.entity.db.BatchImportRecordDo;
import com.corpgovernment.job.batchimport.enums.BatchImportTypeEnum;
import com.corpgovernment.job.batchimport.mapper.BatchImportErrorLineMapper;
import com.corpgovernment.job.controller.vo.job.PageBatchImportErrorLineReqVo;
import com.corpgovernment.job.controller.vo.job.PageBatchImportErrorLineRespVo;
import com.corpgovernment.job.controller.vo.job.PageBatchImportJobRecordReqVo;
import com.corpgovernment.job.controller.vo.job.PageBatchImportJobRecordRespVo;
import com.corpgovernment.job.dao.apollo.JobApolloDao;
import com.corpgovernment.job.dao.dataobject.OrgInfoDo;
import com.corpgovernment.job.dao.entity.db.JobDo;
import com.corpgovernment.job.dao.entity.db.JobOrgRelationDo;
import com.corpgovernment.job.dao.entity.db.JobTypeDo;
import com.corpgovernment.job.dao.mapper.JobMapper;
import com.corpgovernment.job.dao.mapper.JobOrgRelationMapper;
import com.corpgovernment.job.dao.mapper.JobTypeMapper;
import com.corpgovernment.job.service.JobService;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static com.corpgovernment.organization.constant.OrganizationResponseCodeEnum.BATCH_IMPORT_JOB_DATA_ERROR;

/**
 * @author ldma
 * @date 2024/1/9
 */
@Service
public class BatchImportJobService extends BatchImportStrategy<BatchImportJobExcel> {

    @Resource
    private JobTypeMapper jobTypeMapper;
    @Resource
    private JobMapper jobMapper;
    @Resource
    private JobOrgRelationMapper jobOrgRelationMapper;
    @Autowired
    private JobService jobService;
    @Autowired
    private JobApolloDao jobApolloDao;
    @Resource
    private BatchImportErrorLineMapper batchImportErrorLineMapper;

    public void batchImportJob(MultipartFile file, BaseUserInfo baseUserInfo) {
        if (file == null || file.isEmpty() || baseUserInfo == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.REQUEST_PARAM_ERROR);
        }
        Integer errorNum = batchImport(BatchImportTypeEnum.JOB.name(), file, baseUserInfo);
        if (errorNum != 0) {
            throw new CorpBusinessException(BATCH_IMPORT_JOB_DATA_ERROR);
        }
    }

    public PageBatchImportJobRecordRespVo pageBatchImportJobRecord(PageBatchImportJobRecordReqVo requestParam) {
        PageBatchImportJobRecordRespVo result = new PageBatchImportJobRecordRespVo();
        List<String> typeList = Collections.singletonList(BatchImportTypeEnum.JOB.name());
        List<BatchImportRecordDo> batchImportRecordDoList = pageBatchImportRecordDo(typeList, requestParam.getFileName(), requestParam.getOperatorName(), requestParam.getPageNum(), requestParam.getPageSize());
        if (CollectionUtils.isEmpty(batchImportRecordDoList)) {
            result.setRecordCount(0);
            result.setBatchImportJobRecordList(new ArrayList<>(0));
            return result;
        }
        result.setRecordCount(countBatchImportRecordDo(typeList));
        List<PageBatchImportJobRecordRespVo.BatchImportJobRecord> batchImportJobRecordList = batchImportRecordDoList.stream().map(PageBatchImportJobRecordRespVo.BatchImportJobRecord::new).collect(Collectors.toList());
        batchImportJobRecordList.forEach(item -> {
            // 只有导入失败的才能下载
            if (StringUtils.isNotBlank(item.getProcessedFile())) {
                String ossUrl = downLoadFile(item.getProcessedFile());
                if (Boolean.TRUE.equals(checkFileUrl(ossUrl))) {
                    item.setProcessedFile(ossUrl);
                }
            }
        });
        result.setBatchImportJobRecordList(batchImportJobRecordList);
        return result;
    }

    public String downloadJobTemplateExcel() {
        return jobApolloDao.getBatchImportJobTemplateExcel();
    }

    public PageBatchImportErrorLineRespVo pageBatchImportErrorLine(PageBatchImportErrorLineReqVo requestParam) {
        Long recordId = requestParam.getRecordId();
        if (recordId == null) {
            return new PageBatchImportErrorLineRespVo();
        }
        List<BatchImportErrorLineDo> batchImportErrorLineDoList = batchImportErrorLineMapper.listByRecordId(recordId);
        List<PageBatchImportErrorLineRespVo.ErrorLine> errorLineList = batchImportErrorLineDoList.stream().map(item -> new PageBatchImportErrorLineRespVo.ErrorLine(item.getLineNum(), item.getErrorInfo())).collect(Collectors.toList());
        return new PageBatchImportErrorLineRespVo(errorLineList.size(), errorLineList.subList((requestParam.getPageNum()-1)*requestParam.getPageSize(), Math.min(requestParam.getPageNum()*requestParam.getPageSize(), errorLineList.size())));
    }

    private Boolean checkFileUrl(String fileUrl) {
        String regex = "^https:\\/\\/[a-zA-Z0-9\\-\\.]+\\.[a-zA-Z]{2,}(\\/\\S*)?$";
        return ReUtil.isMatch(regex, fileUrl);
    }

    @Override
    public BatchImportConfig<BatchImportJobExcel> batchImportConfigDo() {
        BatchImportConfig<BatchImportJobExcel> batchImportConfig = new BatchImportConfig<>();
        batchImportConfig.setClazz(BatchImportJobExcel.class);
        batchImportConfig.setHeadRowNumber(2);
        batchImportConfig.setErrorCol(4);
        batchImportConfig.setColNameList(Arrays.asList("*岗位名称", "岗位编号", "所属组织编号", "岗位类别"));
        return batchImportConfig;
    }

    @Override
    public Object preStage(BaseUserInfo baseUserInfo) {
        BatchImportJobContext batchImportJobContext = new BatchImportJobContext();
        List<JobDo> jobDoList = jobMapper.listAll();
        if (CollectionUtils.isEmpty(jobDoList)) {
            jobDoList = new ArrayList<>(0);
        }
        batchImportJobContext.setJobNameSet(jobDoList.stream().map(JobDo::getName).collect(Collectors.toSet()));
        batchImportJobContext.setJobCodeSet(jobDoList.stream().map(JobDo::getCode).collect(Collectors.toSet()));

        List<OrgInfoDo> orgInfoList = jobService.listUsableOrg(Optional.ofNullable(baseUserInfo).orElse(new BaseUserInfo()));
        batchImportJobContext.setBusinessCodeToOrgMap(orgInfoList.stream().filter(item -> StringUtils.isNotBlank(item.getBusinessCode())).collect(Collectors.toMap(OrgInfoDo::getBusinessCode, OrgInfoDo::getOrgId, (a,b)->a)));

        List<JobTypeDo> jobTypeDoList = jobTypeMapper.listAll();
        if (CollectionUtils.isEmpty(jobTypeDoList)) {
            jobTypeDoList = new ArrayList<>(0);
        }
        batchImportJobContext.setJobTypeMap(jobTypeDoList.stream().collect(Collectors.toMap(JobTypeDo::getName, JobTypeDo::getId, (a,b)->a)));
        return batchImportJobContext;
    }

    @Override
    public String validateData(BatchImportJobExcel data, Object context) {
        BatchImportJobContext batchImportJobContext = (BatchImportJobContext) context;
        StringBuilder sb = new StringBuilder();
        Set<String> jobNameSet = batchImportJobContext.getJobNameSet();
        Map<String, Long> jobTypeMap = batchImportJobContext.getJobTypeMap();
        Set<String> jobCodeSet = batchImportJobContext.getJobCodeSet();
        Set<String> addJobTypeSet = batchImportJobContext.getAddJobTypeSet();
        Map<String, String> businessCodeToOrgMap = batchImportJobContext.getBusinessCodeToOrgMap();
        // 岗位名称校验
        String jobName = data.getJobName();
        if (StringUtils.isBlank(jobName)) {
            sb.append("岗位名称不能为空；");
        } else {
            if (jobName.length() > 20) {
                sb.append("岗位名称长度不能超过20；");
            }
            if (jobNameSet.contains(jobName)) {
                sb.append("岗位名称重复；");
            }
        }
        // 岗位编号校验
        String jobCode = data.getJobCode();
        if (StringUtils.isNotBlank(jobCode)) {
            if (jobCode.length() > 20) {
                sb.append("岗位编号长度不能超过20；");
            }
            if (jobCodeSet.contains(jobCode)) {
                sb.append("岗位编号重复；");
            }
        }
        // 组织编号校验
        analyzeOrgIdList(data.getBusinessCodeList()).forEach(item -> {
            if (StringUtils.isNotBlank(item) && StringUtils.isBlank(businessCodeToOrgMap.get(item))) {
                sb.append("公司编码").append(item).append("不存在；");
            }
        });
        // 岗位类别
        String jobTypeName = data.getJobTypeName();
        if (StringUtils.isBlank(jobTypeName)) {
            data.setJobTypeName("未分类");
            jobTypeName = "未分类";
        }
        // 校验通过
        jobNameSet.add(jobName);
        jobCodeSet.add(jobCode);
        if (!jobTypeMap.containsKey(jobTypeName)) {
            // 创建岗位类别
            addJobTypeSet.add(jobTypeName);
        }
        return sb.toString();
    }

    @Override
    public void saveData(List<BatchImportJobExcel> dataList, Object context) {
        BatchImportJobContext batchImportJobContext = (BatchImportJobContext) context;
        Set<String> addJobTypeSet = batchImportJobContext.getAddJobTypeSet();
        Map<String, Long> jobTypeMap = batchImportJobContext.getJobTypeMap();
        Map<String, String> businessCodeToOrgMap = batchImportJobContext.getBusinessCodeToOrgMap();
        // 创建岗位类别
        if (CollectionUtils.isNotEmpty(addJobTypeSet)) {
            List<JobTypeDo> jobTypeDoList = addJobTypeSet.stream().map(JobTypeDo::new).collect(Collectors.toList());
            jobTypeMapper.insertList(jobTypeDoList);
            jobTypeDoList.forEach(item -> jobTypeMap.put(item.getName(), item.getId()));
        }
        // 保存岗位
        List<JobDo> jobDoList = new ArrayList<>(0);
        if (CollectionUtils.isNotEmpty(dataList)) {
            jobDoList = dataList.stream().map(item -> new JobDo(item, batchImportJobContext.getJobTypeMap())).collect(Collectors.toList());
            CollUtil.split(jobDoList, 1000).forEach(jobMapper::insertList);
        }
        // 保存岗位组织关系
        Map<String, List<String>> jobOrgRelationMap = dataList.stream().collect(Collectors.toMap(BatchImportJobExcel::getJobName, item -> analyzeOrgIdList(item.getBusinessCodeList()).stream().map(businessCodeToOrgMap::get).collect(Collectors.toList()), (a,b)->a));
        List<JobOrgRelationDo> jobOrgRelationDoList = new ArrayList<>();
        for (JobDo jobDo : jobDoList) {
            Long jobId = jobDo.getId();
            List<String> orgIdList = jobOrgRelationMap.get(jobDo.getName());
            if (CollectionUtils.isNotEmpty(orgIdList)) {
                jobOrgRelationDoList.addAll(orgIdList.stream().map(item -> new JobOrgRelationDo(jobId, item)).collect(Collectors.toList()));
            }
        }
        if (CollectionUtils.isNotEmpty(jobOrgRelationDoList)) {
            CollUtil.split(jobOrgRelationDoList, 1000).forEach(jobOrgRelationMapper::batchCreate);
        }
    }

    private List<String> analyzeOrgIdList(String orgIdList) {
        if (StringUtils.isBlank(orgIdList)) {
            return new ArrayList<>(0);
        }
        return Arrays.asList(orgIdList.replace("；", ";").split(";"));
    }

}
